﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Sinacor.OMM.Configuration.HFTMessageManager;
using System.Configuration;
using System.IO;
using System.Management;
using Sinacor.OMM.Configuration;
using Sinacor.OMM.Configuration.OrderBovespaSystem;
using System.Threading;
using System.Diagnostics;
using Sinacor.OMM.Logging;
using PSE.Framework.Threading;

namespace Sinacor.OMM.HFTMessageManager.ProcessLogic
{
    /// <summary>
    /// Manage the HFT process configuration
    /// </summary>
    public static class HFTConfigurationManager
    {
        static string _configFile;
        static HFTMessageManagerConfiguration _configurationInstance;
        static List<string> _macAddresses = new List<string>();
        static AuthenticationConfiguration _authentication;
        static OrderBovespaSystemConfiguration _orderBovespaSystemInformation;
        static bool _shouldStopRefreshing;
        static Thread messageReaderThread;
        private static object _authenticationLock = new object();

        private static int _numberOfHftProcess;

        public static int NumberOfHftProcess
        {
            get { return _numberOfHftProcess; }
            set { _numberOfHftProcess = value; }
        }

        /// <summary>
        /// Authentication configuration
        /// </summary>
        public static AuthenticationConfiguration Authentication
        {
            get
            {
                try
                {
                    lock (_authenticationLock)
                    {
                        if (_authentication == null)
                            BuildAuthenticationConfiguration();
                    }
                }
                catch (Exception ex)
                {
                    EventLog.WriteEntry("HFT Message Manager Service Configuration", ex.ToString(), EventLogEntryType.Error);
                    throw ex;
                }

                return _authentication;
            }
        }

        /// <summary>
        /// Order Bovespa System Information
        /// </summary>
        public static OrderBovespaSystemConfiguration OrderBovespaSystemInformation
        {
            get
            {
                try
                {
                    if (_orderBovespaSystemInformation == null)
                        BuildOrderBovespaSystemInformation();
                }
                catch (Exception ex)
                {
                    EventLog.WriteEntry(LogSources.HFTMessageManagerService, string.Concat(ex.Message, " ", ex.StackTrace), EventLogEntryType.Error);
                }

                return _orderBovespaSystemInformation;
            }
        }

        /// <summary>
        /// HFT process configuration
        /// </summary>
        public static HFTMessageManagerConfiguration HFTMessageManagerConfiguration
        {
            get
            {
                try
                {
                    if (_configurationInstance == null)
                        BuildHFTMessageManagerConfiguration();
                }
                catch (Exception ex)
                {
                    EventLog.WriteEntry("HFT Message Manager Service Configuration", ex.ToString(), EventLogEntryType.Error);
                    throw ex;
                }

                return _configurationInstance;
            }
        }

        #region Private Methods

        /// <summary>
        /// Get de mac address of machine where the HFT process is installed
        /// </summary>
        /// <returns></returns>
        private static void GetMacAddresses()
        {
            ManagementClass management = new ManagementClass("Win32_NetworkAdapterConfiguration");
            ManagementObjectCollection managementObjects = management.GetInstances();

            foreach (ManagementObject item in managementObjects)
            {
                if ((bool)item["IPEnabled"] == true)
                {
                    _macAddresses.Add(item["MacAddress"].ToString().Replace(":", "").Trim());
                }

                item.Dispose();
            }

            management.Dispose();
            managementObjects.Dispose();
        }

        /// <summary>
        /// Build authentication configuration
        /// </summary>
        private static void BuildAuthenticationConfiguration()
        {
            Int32 companyId;
            Int32 numberOfHftProcess;
            _authentication = new AuthenticationConfiguration();

            if (string.IsNullOrEmpty(_configFile))
                _configFile = Path.Combine(Path.GetDirectoryName(System.Configuration.ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).FilePath), "Sinacor.OMM.HFTMessageManager.exe");

            System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(_configFile);

            if (config == null)
                throw new ConfigurationErrorsException(string.Format("Arquivo de configuração '{0}'.config não encontrado.", _configFile));

            if (!Int32.TryParse(config.AppSettings.Settings["companyId"].Value, out companyId))
                throw new ConfigurationErrorsException(String.Format("Código da empresa não encontrado, impossível realizar a conexão com o banco de dados do Sinacor." + System.Environment.NewLine +
                                                                      "Verificar a tag appSettings do arquivo {0}.config. Verificar a existência da chave  <add key='companyId' value='' />.", _configFile));

            _authentication.CompanyId = companyId;

            if (config.AppSettings.Settings["user"] != null)
                _authentication.User = config.AppSettings.Settings["user"].Value;

            if (config.AppSettings.Settings["password"] != null)
                _authentication.Password = config.AppSettings.Settings["password"].Value;

            if (!Int32.TryParse(config.AppSettings.Settings["numberOfHftProcess"].Value, out numberOfHftProcess))
            {
                NumberOfHftProcess = 0;
            }
            else
            {
                NumberOfHftProcess = numberOfHftProcess;
            }
        }

        /// <summary>
        /// Build order Bovespa system information
        /// </summary>
        private static void BuildOrderBovespaSystemInformation()
        {
            _orderBovespaSystemInformation =
                new OrderBovespaSystemConfigurationReader(Authentication.CompanyId).GetOrderBovespaSystemInformation();
        }

        /// <summary>
        /// Build HFT message manager configuration
        /// </summary>
        private static void BuildHFTMessageManagerConfiguration()
        {
            GetMacAddresses();

            foreach (String macAddress in _macAddresses)
            {
                _configurationInstance = new HFTMessageManagerConfigurationReader(Authentication.CompanyId).GetConfiguration(macAddress);

                if (_configurationInstance != null)
                    break;
            }

            if (_configurationInstance == null)
                throw new ConfigurationErrorsException("Configurações do processo HFT não cadastradas.Verificar a tabela TBOPROS_IAFR.");
        }

        #endregion

        public static void StartRefresh()
        {
            _shouldStopRefreshing = false;
            messageReaderThread = new Thread(new ThreadStart(UpdateConfiguration));
            messageReaderThread.Start();
        }

        /// <summary>
        /// Stop refresh
        /// </summary>
        public static void StopRefresh()
        {
            _shouldStopRefreshing = true;
        }

        /// <summary>
        /// Update the configuration
        /// </summary>
        private static void UpdateConfiguration()
        {
            while (!_shouldStopRefreshing)
            {
                Sleeper.Sleep(60000, () => !_shouldStopRefreshing);
                BuildOrderBovespaSystemInformation();
            }
        }

    }
}
